#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "bus.h"

static bus_t _bus_list_ = 0;
static uint32_t _bus_id_ = 0;

bus_state_t bus_create_state(bus_t bus, char *name)
{
    if (!bus)
        return NULL;
    bus_state_t state = (bus_state_t)malloc(sizeof(bus_state_s));
    if (!state)
        return NULL;
    memset(state, 0, sizeof(bus_state_s));
    state->id = _bus_id_++;
    state->name = name;
    if (bus->state_list)
    {
        bus_state_t end = bus->state_list;
        while (end->next)
            end = end->next;
        end->next = state;
    }
    else
        bus->state_list = state;
    return state;
}

bus_fun_t bus_create_fn(bus_t bus, char *name, uintptr_t fn, bus_fun_param_list_t params)
{
    if (!bus)
        return NULL;
    bus_fun_t fn_item = (bus_fun_t)malloc(sizeof(bus_fun_s));
    if (!fn_item)
        return NULL;
    memset(fn_item, 0, sizeof(bus_fun_s));
    fn_item->id = _bus_id_++;
    fn_item->name = name;
    fn_item->fn = fn;
    fn_item->params = params;
    if (bus->fn_list)
    {
        bus_fun_t end = bus->fn_list;
        while (end->next)
            end = end->next;
        end->next = fn_item;
    }
    else
        bus->fn_list = fn_item;
    return fn_item;
}

void bus_destroy_fn(bus_t bus)
{
    if (!bus || !bus->fn_list)
        return;
    free(bus->fn_list);
}

void bus_destroy_state(bus_t bus)
{
    if (!bus || !bus->state_list)
        return;
    free(bus->state_list);
}

void bus_destroy_obj(bus_t bus)
{
    if (!bus)
        return;
    bus_t end = _bus_list_;
    while (end && end->next != bus)
        end = end->next;
    if (end)
        end->next = bus->next;
    bus_destroy_state(bus);
    bus_destroy_fn(bus);
    free(bus);
}

bus_t bus_create_obj(char *const name)
{
    bus_t bus = (bus_t)malloc(sizeof(bus_s));
    if (!bus)
        return NULL;
    memset(bus, 0, sizeof(bus_s));
    bus->id = _bus_id_++;
    bus->name = name;
    if (_bus_list_)
    {
        bus_t end = _bus_list_;
        while (end->next)
            end = end->next;
        end->next = bus;
    }
    else
        _bus_list_ = bus;
    return bus;
}

/**
 *  [{
        name: "串口0",
        status: [
            { name: "接收", type: "number", value: 0 },
            { name: "发送", type: "number", value: 0 },
        ],
        functions: [
            {
                name: "发送",
                parameters: [{ id: "data", name: "数据", type: "any" }],
            },
            {
                name: "接收",
                parameters: [
                { id: "data", name: "数据接收缓冲区", type: "any" },
                { id: "len", name: "数据接收长度", type: "number" },
                ],
            },
        ],
    },...]
 *  */
uint32_t bus_obj_fn_to_json(bus_fun_t fn, char *buf, uint32_t size)
{
    if (!fn)
        return 0;
    uint32_t len = 0;
    while (fn)
    {
        len += sprintf(&buf[len], "{");
        len += sprintf(&buf[len], "\"name\":\"%s\",", fn->name);
        len += sprintf(&buf[len], "\"parameters\":[");
        if (fn->params)
        {
            bus_fun_param_list_t params = fn->params;
            for (uint8_t i = 0; i < params->param_len; i++)
            {
                bus_fun_param_item_t param = &params->list[i];
                len += sprintf(&buf[len], "{");
                len += sprintf(&buf[len], "\"name\":\"%s\",", param->name);
                len += sprintf(&buf[len], "\"desc\":\"%s\",", param->desc);
                len += sprintf(&buf[len], "\"type\":%d", param->type);
                len += sprintf(&buf[len], "},");
            }
            len--;
        }
        len += sprintf(&buf[len], "]},");
        fn = fn->next;
    }
    len--;
    return len;
}

uint32_t bus_obj_state_to_json(bus_state_t state, char *buf, uint32_t size)
{
    if (!state)
        return 0;
    uint32_t len = 0;
    while (state)
    {
        len += sprintf(&buf[len], "{");
        len += sprintf(&buf[len], "\"id\":\"%ld\",", state->id);
        len += sprintf(&buf[len], "\"name\":\"%s\",", state->name);
        len += sprintf(&buf[len], "\"value\":\"%d\",", state->value);
        len += sprintf(&buf[len], "},");
        state = state->next;
    }
    len--;
    return len;
}

uint32_t bus_obj_to_json(bus_t bus, char *buf, uint32_t size)
{
    if (!bus)
        return 0;
    uint32_t len = 0;
    len += sprintf(&buf[len], "{");
    len += sprintf(&buf[len], "\"name\":\"%s\",", bus->name);
    len += sprintf(&buf[len], "\"status\":[");
    if (bus->state_list)
        len += bus_obj_state_to_json(bus->state_list, &buf[len], size - len);
    len += sprintf(&buf[len], "],");
    len += sprintf(&buf[len], "\"functions\":[");
    if (bus->fn_list)
        len += bus_obj_fn_to_json(bus->fn_list, &buf[len], size - len);
    len += sprintf(&buf[len], "]}");
    return len;
}

uint32_t bus_to_json(char *buf, uint32_t size)
{
    bus_t bus = _bus_list_;
    uint32_t len = 0;
    len += sprintf(&buf[len], "[");
    while (bus)
    {
        len += bus_obj_to_json(bus, &buf[len], size - len);
        len += sprintf(&buf[len], ",");
        bus = bus->next;
    }
    if (len > 1)
        len -= 1;
    len += sprintf(&buf[len], "]");
    return len;
}